<?php
/**
 * Zend Framework
 *
 * LICENSE
 *
 * This source file is subject to the new BSD license that is bundled
 * with this package in the file LICENSE.txt.
 * It is also available through the world-wide-web at this URL:
 * http://framework.zend.com/license/new-bsd
 * If you did not receive a copy of the license and are unable to
 * obtain it through the world-wide-web, please send an email
 * to license@zend.com so we can send you a copy immediately.
 *
 * @category   Zend
 * @package    Zend_Gdata
 * @subpackage Demos
 * @copyright  Copyright (c) 2005-2011 Zend Technologies USA Inc. (http://www.zend.com)
 * @license    http://framework.zend.com/license/new-bsd     New BSD License
 */

/**
 * PHP sample code for the Google Calendar data API.  Utilizes the
 * Zend Framework Gdata components to communicate with the Google API.
 *
 * Requires the Zend Framework Gdata components and PHP >= 5.1.4
 *
 * You can run this sample both from the command line (CLI) and also
 * from a web browser.  When running through a web browser, only
 * AuthSub and outputting a list of calendars is demonstrated.  When
 * running via CLI, all functionality except AuthSub is available and dependent
 * upon the command line options passed.  Run this script without any
 * command line options to see usage, eg:
 * /usr/local/bin/php -f Calendar.php
 *
 * More information on the Command Line Interface is available at:
 * http://www.php.net/features.commandline
 *
 * NOTE: You must ensure that the Zend Framework is in your PHP include
 * path.  You can do this via php.ini settings, or by modifying the
 * argument to set_include_path in the code below.
 *
 * NOTE: As this is sample code, not all of the functions do full error
 * handling.  Please see getEvent for an example of how errors could
 * be handled and the online code samples for additional information.
 */

class Evebit_Gdata_Calendar extends Zend_Gdata_Calendar {
	/**
	 * Returns the full URL of the current page, based upon env variables
	 *
	 * Env variables used:
	 * $_SERVER['HTTPS'] = (on|off|)
	 * $_SERVER['HTTP_HOST'] = value of the Host: header
	 * $_SERVER['SERVER_PORT'] = port number (only used if not http/80,https/443)
	 * $_SERVER['REQUEST_URI'] = the URI after the method of the HTTP request
	 *
	 * @return string Current URL
	 */
	public static function getCurrentUrl() {
		global $_SERVER;
		
		/**
		 * Filter php_self to avoid a security vulnerability.
		 */
		$php_request_uri = htmlentities ( substr ( $_SERVER ['REQUEST_URI'], 0, strcspn ( $_SERVER ['REQUEST_URI'], "\n\r" ) ), ENT_QUOTES );
		
		if (isset ( $_SERVER ['HTTPS'] ) && strtolower ( $_SERVER ['HTTPS'] ) == 'on') {
			$protocol = 'https://';
		} else {
			$protocol = 'http://';
		}
		$host = $_SERVER ['HTTP_HOST'];
		if ($_SERVER ['SERVER_PORT'] != '' && (($protocol == 'http://' && $_SERVER ['SERVER_PORT'] != '80') || ($protocol == 'https://' && $_SERVER ['SERVER_PORT'] != '443'))) {
			$port = ':' . $_SERVER ['SERVER_PORT'];
		} else {
			$port = '';
		}
		return $protocol . $host . $port . $php_request_uri;
	}
	
	public static function processPageLoad() {
		global $_SESSION, $_GET;
		if (! isset ( $_SESSION ['sessionToken'] )) {
			self::requestUserLogin ( 'Please login to your Google Account.' );
		} else {
			$client = self::getAuthSubHttpClient ();
			return $client;
		}
	}
	
	/**
	 * Returns the AuthSub URL which the user must visit to authenticate requests
	 * from this application.
	 *
	 * Uses getCurrentUrl() to get the next URL which the user will be redirected
	 * to after successfully authenticating with the Google service.
	 *
	 * @return string AuthSub URL
	 */
	public static function getAuthSubUrl() {
		global $_authSubKeyFile;
		$next = Evebit_Gdata_Calendar::getCurrentUrl ();
		$scope = 'http://www.google.com/calendar/feeds/';
		$session = true;
		if ($_authSubKeyFile != null) {
			$secure = true;
		} else {
			$secure = false;
		}
		return Zend_Gdata_AuthSub::getAuthSubTokenUri ( $next, $scope, $secure, $session );
	}
	
	/**
	 * Outputs a request to the user to login to their Google account, including
	 * a link to the AuthSub URL.
	 *
	 * Uses getAuthSubUrl() to get the URL which the user must visit to authenticate
	 *
	 * @return void
	 */
	public static function requestUserLogin($linkText) {
		$authSubUrl = Evebit_Gdata_Calendar::getAuthSubUrl ();
		echo "<a href=\"{$authSubUrl}\">{$linkText}</a>";
		exit ();
	}
	
	/**
	 * Returns a HTTP client object with the appropriate headers for communicating
	 * with Google using AuthSub authentication.
	 *
	 * Uses the $_SESSION['sessionToken'] to store the AuthSub session token after
	 * it is obtained.  The single use token supplied in the URL when redirected
	 * after the user succesfully authenticated to Google is retrieved from the
	 * $_GET['token'] variable.
	 *
	 * @return Zend_Http_Client
	 */
	public static function getAuthSubHttpClient() {
		global $_SESSION, $_GET, $_authSubKeyFile, $_authSubKeyFilePassphrase;
		$client = new Zend_Gdata_HttpClient ();
		if ($_authSubKeyFile != null) {
			// set the AuthSub key
			$client->setAuthSubPrivateKeyFile ( $_authSubKeyFile, $_authSubKeyFilePassphrase, true );
		}
		if (! isset ( $_SESSION ['sessionToken'] ) && isset ( $_GET ['token'] )) {
			$_SESSION ['sessionToken'] = Zend_Gdata_AuthSub::getAuthSubSessionToken ( $_GET ['token'], $client );
		}
		$client->setAuthSubToken ( $_SESSION ['sessionToken'] );
		return $client;
	}
	
	/**
	 * Returns a HTTP client object with the appropriate headers for communicating
	 * with Google using the ClientLogin credentials supplied.
	 *
	 * @param  string $user The username, in e-mail address format, to authenticate
	 * @param  string $pass The password for the user specified
	 * @return Zend_Http_Client
	 */
	public function getClientLoginHttpClient($user, $pass) {
		$service = Zend_Gdata_Calendar::AUTH_SERVICE_NAME;
		
		$client = Zend_Gdata_ClientLogin::getHttpClient ( $user, $pass, $service );
		return $client;
	}
	
	/**
	 * Outputs an HTML unordered list (ul), with each list item representing an
	 * event on the authenticated user's calendar.  Includes the start time and
	 * event ID in the output.  Events are ordered by starttime and include only
	 * events occurring in the future.
	 *
	 * @param  Zend_Http_Client $client The authenticated client object
	 * @return void
	 */
	public function outputCalendar() {
		$query = $this->newEventQuery ();
		$query->setUser ( 'default' );
		$query->setVisibility ( 'private' );
		$query->setProjection ( 'full' );
		$query->setOrderby ( 'starttime' );
		$query->setFutureevents ( true );
		$eventFeed = $this->getCalendarEventFeed ( $query );
		return $eventFeed;
	}
	
	/**
	 * Outputs an HTML unordered list (ul), with each list item representing an
	 * event on the authenticated user's calendar which occurs during the
	 * specified date range.
	 *
	 * To query for all events occurring on 2006-12-24, you would query for
	 * a startDate of '2006-12-24' and an endDate of '2006-12-25' as the upper
	 * bound for date queries is exclusive.  See the 'query parameters reference':
	 * http://code.google.com/apis/gdata/calendar.html#Parameters
	 *
	 * @param  Zend_Http_Client $client    The authenticated client object
	 * @param  string           $startDate The start date in YYYY-MM-DD format
	 * @param  string           $endDate   The end date in YYYY-MM-DD format
	 * @return void
	 */
	public function outputCalendarByDateRange($startDate = '2007-05-01', $endDate = '2007-08-01') {
		$query = $this->newEventQuery ();
		$query->setUser ( 'default' );
		$query->setVisibility ( 'private' );
		$query->setProjection ( 'full' );
		$query->setOrderby ( 'starttime' );
		$query->setStartMin ( $startDate );
		$query->setStartMax ( $endDate );
		$eventFeed = $this->getCalendarEventFeed ( $query );
		return $eventFeed;
	}
	
	/**
	 * Outputs an HTML unordered list (ul), with each list item representing an
	 * event on the authenticated user's calendar which matches the search string
	 * specified as the $fullTextQuery parameter
	 *
	 * @param  Zend_Http_Client $client        The authenticated client object
	 * @param  string           $fullTextQuery The string for which you are searching
	 * @return void
	 */
	public function outputCalendarByFullTextQuery($fullTextQuery = 'tennis') {
		$query = $this->newEventQuery ();
		$query->setUser ( 'default' );
		$query->setVisibility ( 'private' );
		$query->setProjection ( 'full' );
		$query->setQuery ( $fullTextQuery );
		$eventFeed = $this->getCalendarEventFeed ( $query );
		return $eventFeed;
	}
	
	/*public static function createEvent($client, $title = 'Tennis with Beth', $desc = 'Meet for a quick lesson', $where = 'On the courts', $startDate = '2008-01-20', $startTime = '10:00', $endDate = '2008-01-20', $endTime = '11:00', $tzOffset = '-08') {*/
	/*public static function createEvent($client, $data) {
		$title = isset ( $data ['title'] ) ? $data ['title'] : 'Tennis with Beth';
		$desc = isset ( $data ['desc'] ) ? $data ['desc'] : 'Meet for a quick lesson';
		$where = isset ( $data ['where'] ) ? $data ['where'] : 'On the courts';
		$startDate = isset ( $data ['start_date'] ) ? $data ['start_date'] : '';
		$endDate = isset ( $data ['end_date'] ) ? $data ['end_date'] : '';
		$startTime = isset ( $data ['start_time'] ) ? $data ['start_time'] : '';
		$endTime = isset ( $data ['end_time'] ) ? $data ['end_time'] : '';
		$tzOffset = '-08';
		
		$gdataCal = new Zend_Gdata_Calendar ( $client );
		$newEvent = $gdataCal->newEventEntry ();
		
		$newEvent->title = $gdataCal->newTitle ( $title );
		$newEvent->where = array ($gdataCal->newWhere ( $where ) );
		$newEvent->content = $gdataCal->newContent ( "$desc" );
		
		$when = $gdataCal->newWhen ();
		$when->startTime = "{$startDate}T{$startTime}.000{$tzOffset}:00";
		$when->endTime = "{$endDate}T{$endTime}.000{$tzOffset}:00";
		$newEvent->when = array ($when );
		
		// Upload the event to the calendar server
		// A copy of the event as it is recorded on the server is returned
		$createdEvent = $gdataCal->insertEvent ( $newEvent );
		return $createdEvent->id->text;
	}*/
	
	/**
	 * Creates an event on the authenticated user's default calendar with the
	 * specified event details.
	 *
	 * @param  Zend_Http_Client $client    The authenticated client object
	 * @param  string           $title     The event title
	 * @param  string           $desc      The detailed description of the event
	 * @param  string           $where
	 * @param  string           $startDate The start date of the event in YYYY-MM-DD format
	 * @param  string           $startTime The start time of the event in HH:MM 24hr format
	 * @param  string           $endDate   The end date of the event in YYYY-MM-DD format
	 * @param  string           $endTime   The end time of the event in HH:MM 24hr format
	 * @param  string           $tzOffset  The offset from GMT/UTC in [+-]DD format (eg -08)
	 * @return string The ID URL for the event.
	 */
	public function createEvent($data = null) {
		$title = isset ( $data ['title'] ) ? $data ['title'] : 'Tennis with Beth';
		$desc = isset ( $data ['desc'] ) ? $data ['desc'] : 'Meet for a quick lesson';
		$where = isset ( $data ['where'] ) ? $data ['where'] : 'On the courts';
		$startDate = isset ( $data ['start_date'] ) ? $data ['start_date'] : '';
		$endDate = isset ( $data ['end_date'] ) ? $data ['end_date'] : '';
		$startTime = isset ( $data ['start_time'] ) ? $data ['start_time'] : '';
		$endTime = isset ( $data ['end_time'] ) ? $data ['end_time'] : '';
		$tzOffset = '-08';
		
		$newEntry = $this->newEventEntry ();
		$newEntry->title = $this->newTitle ( trim ( $title ) );
		$newEntry->where = array ($this->newWhere ( $where ) );
		
		$newEntry->content = $this->newContent ( $desc );
		$newEntry->content->type = 'text';
		
		$when = $this->newWhen ();
		$when->startTime = "{$startDate}T{$startTime}.000{$tzOffset}:00";
		$when->endTime = "{$endDate}T{$endTime}.000{$tzOffset}:00";
		$newEntry->when = array ($when );
		
		$a = $this->outputCalendarByDateRange ( $startTime, $endTime );
		if (count ( $a )) {
			return false;
		}
		
		$createdEntry = $this->insertEvent ( $newEntry );
		$result ['url'] = $createdEntry->id->text;
		$result ['eventId'] = array_pop ( explode ( '/', $result ['url'] ) );
		return $result;
	}
	
	/**
	 * Creates an event on the authenticated user's default calendar using
	 * the specified QuickAdd string.
	 *
	 * @param  Zend_Http_Client $client       The authenticated client object
	 * @param  string           $quickAddText The QuickAdd text for the event
	 * @return string The ID URL for the event
	 */
	public function createQuickAddEvent($quickAddText) {
		$event = $this->newEventEntry ();
		$event->content = $this->newContent ( $quickAddText );
		$event->quickAdd = $this->newQuickAdd ( true );
		
		$newEvent = $this->insertEvent ( $event );
		return $newEvent->id->text;
	}
	
	/**
	 * Creates a new web content event on the authenticated user's default
	 * calendar with the specified event details. For simplicity, the event
	 * is created as an all day event and does not include a description.
	 *
	 * @param  Zend_Http_Client $client    The authenticated client object
	 * @param  string           $title     The event title
	 * @param  string           $startDate The start date of the event in YYYY-MM-DD format
	 * @param  string           $endDate   The end time of the event in HH:MM 24hr format
	 * @param  string           $icon      URL pointing to a 16x16 px icon representing the event.
	 * @param  string           $url       The URL containing the web content for the event.
	 * @param  string           $height    The desired height of the web content pane.
	 * @param  string           $width     The desired width of the web content pane.
	 * @param  string           $type      The MIME type of the web content.
	 * @return string The ID URL for the event.
	 */
	public function createWebContentEvent($title = 'World Cup 2006', $startDate = '2006-06-09', $endDate = '2006-06-09', $icon = 'http://www.google.com/calendar/images/google-holiday.gif', $url = 'http://www.google.com/logos/worldcup06.gif', $height = '120', $width = '276', $type = 'image/gif') {
		$newEntry = $this->newEventEntry ();
		$newEntry->title = $this->newTitle ( trim ( $title ) );
		
		$when = $this->newWhen ();
		$when->startTime = $startDate;
		$when->endTime = $endDate;
		$newEntry->when = array ($when );
		
		$wc = $this->newWebContent ();
		$wc->url = $url;
		$wc->height = $height;
		$wc->width = $width;
		
		$wcLink = $this->newLink ();
		$wcLink->rel = "http://schemas.google.com/gCal/2005/webContent";
		$wcLink->title = $title;
		$wcLink->type = $type;
		$wcLink->href = $icon;
		
		$wcLink->webContent = $wc;
		$newEntry->link = array ($wcLink );
		
		$createdEntry = $this->insertEvent ( $newEntry );
		return $createdEntry->id->text;
	}
	
	/**
	 * Creates a recurring event on the authenticated user's default calendar with
	 * the specified event details.
	 *
	 * @param  Zend_Http_Client $client    The authenticated client object
	 * @param  string           $title     The event title
	 * @param  string           $desc      The detailed description of the event
	 * @param  string           $where
	 * @param  string           $recurData The iCalendar recurring event syntax (RFC2445)
	 * @return void
	 */
	public function createRecurringEvent($title = 'Tennis with Beth', $desc = 'Meet for a quick lesson', $where = 'On the courts', $recurData = null) {
		$newEntry = $this->newEventEntry ();
		$newEntry->title = $this->newTitle ( trim ( $title ) );
		$newEntry->where = array ($this->newWhere ( $where ) );
		
		$newEntry->content = $this->newContent ( $desc );
		$newEntry->content->type = 'text';
		
		/**
		 * Due to the length of this recurrence syntax, we did not specify
		 * it as a default parameter value directly
		 */
		if ($recurData == null) {
			$recurData = "DTSTART;VALUE=DATE:20070501\r\n" . "DTEND;VALUE=DATE:20070502\r\n" . "RRULE:FREQ=WEEKLY;BYDAY=Tu;UNTIL=20070904\r\n";
		}
		
		$newEntry->recurrence = $this->newRecurrence ( $recurData );
		
		$this->post ( $newEntry->saveXML () );
	}
	
	/**
	 * Returns an entry object representing the event with the specified ID.
	 *
	 * @param  Zend_Http_Client $client  The authenticated client object
	 * @param  string           $eventId The event ID string
	 * @return Zend_Gdata_Calendar_EventEntry|null if the event is found, null if it's not
	 */
	public function getEvent($eventId) {
		$query = $this->newEventQuery ();
		$query->setUser ( 'default' );
		$query->setVisibility ( 'private' );
		$query->setProjection ( 'full' );
		$query->setEvent ( $eventId );
		
		try {
			$eventEntry = $this->getCalendarEventEntry ( $query );
			return $eventEntry;
		} catch ( Zend_Gdata_App_Exception $e ) {
			var_dump ( $e );
			return null;
		}
	}
	
	/**
	 * Updates the title of the event with the specified ID to be
	 * the title specified.  Also outputs the new and old title
	 * with HTML br elements separating the lines
	 *
	 * @param  string           $eventId  The event ID string
	 * @param  string           $newTitle The new title to set on this event
	 * @return Zend_Gdata_Calendar_EventEntry|null The updated entry
	 */
	public function updateEvent($eventId, $newTitle) {
		if ($eventOld = $this->getEvent ( $eventId )) {
			$eventOld->title = $this->newTitle ( $newTitle );
			try {
				$eventOld->save ();
			} catch ( Zend_Gdata_App_Exception $e ) {
				var_dump ( $e );
				return null;
			}
			$eventNew = $this->getEvent ( $eventId );
			echo "New title: " . $eventNew->title->text . "<br />\n";
			return $eventNew;
		} else {
			return null;
		}
	}
	
	/**
	 * Adds an extended property to the event specified as a parameter.
	 * An extended property is an arbitrary name/value pair that can be added
	 * to an event and retrieved via the API.  It is not accessible from the
	 * calendar web interface.
	 *
	 * @param  string           $eventId The event ID string
	 * @param  string           $name    The name of the extended property
	 * @param  string           $value   The value of the extended property
	 * @return Zend_Gdata_Calendar_EventEntry|null The updated entry
	 */
	public function addExtendedProperty($eventId, $name = 'http://www.example.com/schemas/2005#mycal.id', $value = '1234') {
		if ($event = getEvent ( $eventId )) {
			$extProp = $this->newExtendedProperty ( $name, $value );
			$extProps = array_merge ( $event->extendedProperty, array ($extProp ) );
			$event->extendedProperty = $extProps;
			$eventNew = $event->save ();
			return $eventNew;
		} else {
			return null;
		}
	}
	
	/**
	 * Adds a reminder to the event specified as a parameter.
	 *
	 * @param  string           $eventId The event ID string
	 * @param  integer          $minutes Minutes before event to set reminder
	 * @return Zend_Gdata_Calendar_EventEntry|null The updated entry
	 */
	public function setReminder($eventId, $data = null) {
		$reminderMethod = isset ( $data ['reminder_method'] ) ? $data ['reminder_method'] : 'sms';
		$reminderTime = isset ( $data ['reminder_time'] ) ? $data ['reminder_time'] : '30';
		if ($event = $this->getEvent ( $eventId )) {
			$times = $event->when;
			foreach ( $times as $when ) {
				$reminder = $this->newReminder ();
				$reminder->setMinutes ( $reminderTime );
				$reminder->setMethod ( $reminderMethod );
				$when->reminders = array ($reminder );
			}
			$eventNew = $event->save ();
			return $eventNew;
		} else {
			return null;
		}
	}
	
	/**
	 * Deletes the event specified by retrieving the atom entry object
	 * and calling Zend_Feed_EntryAtom::delete() method.  This is for
	 * example purposes only, as it is inefficient to retrieve the entire
	 * atom entry only for the purposes of deleting it.
	 *
	 * @param  string           $eventId The event ID string
	 * @return void
	 */
	public function deleteEventById($eventId) {
		$event = $this->getEvent ( $eventId );
		$event->delete ();
	}
	
	/**
	 * Deletes the event specified by calling the Zend_Gdata::delete()
	 * method.  The URL is typically in the format of:
	 * http://www.google.com/calendar/feeds/default/private/full/<eventId>
	 *
	 * @param  Zend_Http_Client $client The authenticated client object
	 * @param  string           $url    The url for the event to be deleted
	 * @return void
	 */
	public function deleteEventByUrl($url) {
		$this->delete ( $url );
	}

}